package com.eas.task.examStatistic;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import com.eas.biz.constants.BizConstants;
import com.eas.biz.dao.statistic.dataobject.BaseStudentQuestionStatisticDO;
import com.eas.biz.dao.statistic.dataobject.StudentQuestionStatisticDO;
import com.eas.biz.dao.statistic.dataobject.StudentStatisticQuery;
import com.eas.biz.dao.statistic.dataobject.StudentTagStatisticDO;
import com.eas.biz.dao.statistic.interfaces.StudentQuestionStatisticDao;
import com.eas.biz.dao.statistic.interfaces.StudentTagStatisticDao;
import com.eas.biz.dao.user.dataobject.StudentDO;
import com.eas.biz.service.exam.domain.Exam;
import com.eas.biz.service.exam.domain.ExamQuestionDetail;
import com.eas.biz.service.exam.domain.ExamSubjectDetail;
import com.eas.biz.service.exam.interfaces.ExamService;
import com.eas.biz.service.examResult.domain.ExamQuestionResult;
import com.eas.biz.service.examResult.domain.ExamResult;
import com.eas.biz.service.examResult.domain.ExamSubjectResult;
import com.eas.biz.service.examResult.interfaces.ExamResultService;
import com.eas.biz.service.user.interfaces.StudentService;

public class StudentStatisticJob {

    public static final String JOB_TARGET = "student";

    @Resource(name = "examService")
    private ExamService examService;

    @Autowired
    private ExamResultService examResultService;

    @Autowired
    private StudentService studentService;

    @Autowired
    private StudentTagStatisticDao studentTagStatisticDao;

    @Autowired
    private StudentQuestionStatisticDao studentQuestionStatisticDao;

    private long studentId;

    private long examId;

    private StudentDO studentDO;

    private Exam examDetail;

    public void work() {
        init();

        ExamResult result = examResultService.getExamResult(examId, studentId, true);
        if (result == null || result.getSubjectResultMap().size() == 0) {
            return;
        }

        for (ExamSubjectResult subjectResult : result.getSubjectResultMap().values()) {
            if (!subjectResult.getSubject().equals(BizConstants.TOTAL_SCORE_SUBJECT)) {
                statisticSubject(subjectResult);
            }
        }
    }

    private void init() {
        if (studentDO == null) {
            studentDO = studentService.selectById(studentId);
        }

        if (examDetail == null) {
            examDetail = examService.getExamDetail(examId);
        }
    }

    private void statisticSubject(ExamSubjectResult subjectResult) {
        ExamSubjectDetail subjectDetail = examDetail.getSubjectDetail(subjectResult.getSubject());
        if (subjectDetail == null) {
            return;
        }

        Map<String, StudentTagStatisticDO> tagMap = new HashMap<String, StudentTagStatisticDO>();
        Map<String, StudentQuestionStatisticDO> typeMap = new HashMap<String, StudentQuestionStatisticDO>();

        List<ExamQuestionResult> questionResultList = examResultService
                .getQuestionResultList(subjectResult);
        if (questionResultList != null && questionResultList.size() > 0) {
            for (ExamQuestionResult questionResult : questionResultList) {
                ExamQuestionDetail questionDetail = subjectDetail.getQuestionDetail(questionResult
                        .getQuestionNumber());
                if (questionDetail != null) {
                    countQuestionType(questionResult, questionDetail, typeMap);
                    countQuestionTag(questionResult, questionDetail, tagMap);
                }
            }
        }

        saveQuestionTypeStatistic(subjectResult.getSubject(), typeMap);
        saveQuestionTagStatistic(subjectResult.getSubject(), tagMap);

        typeMap.clear();
        tagMap.clear();
    }

    private void countQuestionTag(ExamQuestionResult questionResult,
            ExamQuestionDetail questionDetail, Map<String, StudentTagStatisticDO> tagMap) {
        String primaryTag = questionDetail.getPrimaryTag();
        if (StringUtils.isNotBlank(primaryTag)) {
            StudentTagStatisticDO tagCounter = tagMap.get(primaryTag);
            if (tagCounter == null) {
                tagCounter = new StudentTagStatisticDO();
                tagCounter.setTag(primaryTag);
                tagCounter.setCorrectCount(0);
                tagCounter.setErrorCount(0);
                tagMap.put(primaryTag, tagCounter);
            }
            increment(tagCounter, questionDetail, questionResult);
        }

        if (questionDetail.getTags() != null && questionDetail.getTags().size() > 0) {
            for (String tag : questionDetail.getTags()) {
                StudentTagStatisticDO tagCounter = tagMap.get(tag);
                if (tagCounter == null) {
                    tagCounter = new StudentTagStatisticDO();
                    tagCounter.setTag(tag);
                    tagCounter.setTotalCount(0);
                    tagCounter.setCorrectCount(0);
                    tagCounter.setErrorCount(0);
                    tagCounter.setTotalScore(0F);
                    tagCounter.setScore(0F);
                    tagMap.put(tag, tagCounter);
                }
                increment(tagCounter, questionDetail, questionResult);
            }
        }
    }

    private void countQuestionType(ExamQuestionResult questionResult,
            ExamQuestionDetail questionDetail, Map<String, StudentQuestionStatisticDO> typeMap) {
        String questionType = questionDetail.getQuestionType();
        if (StringUtils.isBlank(questionType)) {
            return;
        }

        StudentQuestionStatisticDO typeCounter = typeMap.get(questionType);
        if (typeCounter == null) {
            typeCounter = new StudentQuestionStatisticDO();
            typeCounter.setTotalCount(0);
            typeCounter.setCorrectCount(0);
            typeCounter.setErrorCount(0);
            typeCounter.setTotalScore(0F);
            typeCounter.setScore(0F);
            typeCounter.setQuestionType(questionType);
            typeMap.put(questionType, typeCounter);
        }
        increment(typeCounter, questionDetail, questionResult);
    }

    private void increment(BaseStudentQuestionStatisticDO statisticDO,
            ExamQuestionDetail questionDetail, ExamQuestionResult questionResult) {
        if (questionResult.getScore() < questionDetail.getScore()) {
            statisticDO.setErrorCount(statisticDO.getErrorCount() + 1);
        } else {
            statisticDO.setCorrectCount(statisticDO.getCorrectCount() + 1);
        }
        statisticDO.setTotalCount(statisticDO.getTotalCount() + 1);
        statisticDO.setTotalScore(statisticDO.getTotalScore() + questionDetail.getScore());
        statisticDO.setScore(statisticDO.getScore() + questionResult.getScore());
    }

    private void saveQuestionTypeStatistic(String subject,
            Map<String, StudentQuestionStatisticDO> typeMap) {
        if (typeMap.size() == 0) {
            return;
        }

        StudentStatisticQuery query = new StudentStatisticQuery();
        query.setStudentId(studentId);
        query.setExamId(examId);
        query.setSubject(subject);
        studentQuestionStatisticDao.deleteByQuery(query);

        for (StudentQuestionStatisticDO sqsDO : typeMap.values()) {
            if (sqsDO.getTotalCount().intValue() == 0) {
                continue;
            }
            sqsDO.setStudentId(studentId);
            sqsDO.setExamId(examId);
            sqsDO.setClassId(studentDO.getClassId());
            sqsDO.setSubject(subject);
            studentQuestionStatisticDao.insert(sqsDO);
        }
    }

    private void saveQuestionTagStatistic(String subject, Map<String, StudentTagStatisticDO> tagMap) {
        if (tagMap.size() == 0) {
            return;
        }

        StudentStatisticQuery query = new StudentStatisticQuery();
        query.setStudentId(studentId);
        query.setExamId(examId);
        query.setSubject(subject);
        studentTagStatisticDao.deleteByQuery(query);

        for (StudentTagStatisticDO stsDO : tagMap.values()) {
            if (stsDO.getTotalCount().intValue() == 0) {
                continue;
            }
            stsDO.setStudentId(studentId);
            stsDO.setExamId(examId);
            stsDO.setClassId(studentDO.getClassId());
            stsDO.setSubject(subject);
            studentTagStatisticDao.insert(stsDO);
        }
    }

    public long getStudentId() {
        return studentId;
    }

    public void setStudentId(long studentId) {
        this.studentId = studentId;
    }

    public long getExamId() {
        return examId;
    }

    public void setExamId(long examId) {
        this.examId = examId;
    }

    public Exam getExamDetail() {
        return examDetail;
    }

    public void setExamDetail(Exam examDetail) {
        this.examDetail = examDetail;
    }
}
